﻿using Caltech.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Caltech.Results;
using CaltechSoft.Service.CommandService;
using ServiceModel = CaltechSoft.Service.DBCommand;
using AutoMapper;
using CaltechSoft.Service.ReportService;
using CaltechSoft.Service.SearchCriteria;
using CaltechSoft.Service.Repositories;
using CaltechSoft.Service.EntityFW.Entity;
using System.Linq.Expressions;
using System.Threading.Tasks;
using CaltechSoft.Service.Infrastructure.Utility;
using Microsoft.AspNet.Identity;
using Caltech.Service.Common;
using Caltech.Extensions;

namespace Caltech.Controllers
{    
    public class CustomerController : BaseApiController<Customer, CustomerModel, CustomerModel>
    {
        public UserManager<User> UserManager { get; private set; }
        private readonly ICustomerCommandService _customerCommandService;

        public CustomerController(IRepository<Customer> repository, UserManager<User> userManager, ICustomerCommandService customerCommandService)
            : base(repository)
        {
            UserManager = userManager;
            _customerCommandService = customerCommandService;
        }

        [Route("api/customer/list")]
        public IHttpActionResult GetCompactList(string name = null)
        {
            var data = Repository.DbSet().Where(customer => customer.Name.ToLower().Contains(name.ToLower())).Take(10);
            var result = Mapper.Map<IEnumerable<CustomerCompactModel>>(data);
            return Request.CreateSearchResult<CustomerCompactModel>(result);
        }

        public override IHttpActionResult Get()
        {
            var queryItems = Request.RequestUri.ParseQueryString();
            string name = queryItems["name"];
            Expression<Func<Customer, bool>> filter = null;

            if (!string.IsNullOrEmpty(name))
            {
                filter = customer => customer.Name.Contains(name);
            }

            return QueryData(filter);
        }

        [HasAccess(Areas.Customer)]
        public override async Task<IHttpActionResult> Post(CustomerModel model)
        {
            if (!string.IsNullOrEmpty(model.LoginUsername) && !string.IsNullOrEmpty(model.LoginPassword))
            {
                Guard.Against<Exception>(model.LoginPassword.Trim().Length < 6, "Password must be at least 6 characters!");
                Guard.Against<ArgumentException>(!EmailUtilities.ValidateEmailAddress(model.LoginUsername), "The customer username should follow email format!");
                User user = new User { UserName = model.LoginUsername };

                var result = await UserManager.CreateAsync(user, model.LoginPassword);
                Guard.Against<Exception>(!result.Succeeded, result.Errors.FirstOrDefault());

                var role = Roles.Customer;
                result = await UserManager.AddToRoleAsync(user.Id, role.ToString());
                Guard.Against<Exception>(!result.Succeeded, result.Errors.FirstOrDefault());
            }
            else
            {
                model.LoginUsername = null;
            }

            var entity = Mapper.Map<Customer>(model);
            entity.CreatedDate = DateTime.Now;

            var id = _customerCommandService.AddCustomer(entity);

            return Ok(id);
        }

        [HasAccess(Areas.Customer)]
        public override async Task<IHttpActionResult> Put(CustomerModel model)
        {
            if (!string.IsNullOrEmpty(model.LoginUsername) && !string.IsNullOrEmpty(model.LoginPassword))
            {
                Guard.Against<Exception>(model.LoginPassword.Trim().Length < 6, "Password must be at least 6 characters!");
                Guard.Against<ArgumentException>(!EmailUtilities.ValidateEmailAddress(model.LoginUsername), "The customer username should follow email format!");
                User user = new User { UserName = model.LoginUsername };

                var result = await UserManager.CreateAsync(user, model.LoginPassword);
                Guard.Against<Exception>(!result.Succeeded, result.Errors.FirstOrDefault());

                var role = Roles.Customer;
                result = await UserManager.AddToRoleAsync(user.Id, role.ToString());
                Guard.Against<Exception>(!result.Succeeded, result.Errors.FirstOrDefault());
            }

            model.User = null;

            var entity = Mapper.Map<Customer>(model);
            entity.UpdatedDate = DateTime.Now;
            var id = _customerCommandService.UpdateCustomer(entity);

            return Ok(id);
        }

        [HasAccess(Areas.Customer)]
        public override async Task<IHttpActionResult> Delete(int id)
        {
            _customerCommandService.DeleteCustomer(id);
            return Ok(id);
        }
    }
}